package thread;
/** 当多个线程并发操作同一临界资源，由于线程切换实际不确定，导致执行顺序出现混乱从而产生不良后果
 * 并发安全问题
 *
 * 临界资源：操作该资源的过程同时只能被多个线程进行*/
public class SyncDemo1 {
    static boolean success1 = false;//表示第一个人是否取款成功
    static boolean success2 = false;//表示第二个人是否取款成功

    public static void main(String[] args) throws InterruptedException {
        Bank bank = new Bank(); // 创建一个银行账户对象
        int sum = 0;// 记录测试的次数
        while (true) {
            sum ++;

                    Thread t1 = new Thread() {
                public void run() {
                    success1 = bank.getMoney(20000);//取钱
                }
            };
            Thread t2 = new Thread() {
                public void run() {
                    success2 = bank.getMoney(20000);//取钱
                }
            };
            t1.start();
            t2.start();
            Thread.sleep(5);//阻塞主线程一段时间，用于让t1,t2线程执行完毕
            if (success1 && success2) {
                System.out.println("卡BUG成功两个人都取出来了20000共测试"+sum+"次");
                break;
            } else {
               // System.out.println("取钱失败");
                success1 = false;
                success2 = false;
                bank.saveAccount(20000);
            }
            // TODO: Add main method implementation
        }
    }
}

class Bank {
    private int account = 20000; // 银行账号的余额

    // 取钱方法，返回true说明允许出钞，否则拒绝出钞
    // synchronized 同步     异步     排队  效率低
    public   synchronized    boolean getMoney(int money) {
        int account = getAccount(); // 查询余额
        if ( account >= money) { // 判断余额是否多余要取的钱
            account =  account- money; // 扣款
            Thread.yield();//主动让线程放弃时间片，模拟到这里本次时间片用完
            saveAccount(account);//保存新余额
            return true;//允许出钞
        }
        return false;//拒绝出钞
    }

    public void saveAccount(int account) {
        this .account = account;
    }

    public int getAccount() {
        return account;
    }
}

